package com.etop.rediscache;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

import javax.annotation.Resource;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.log4j.Logger;



public class MethodCacheInterceptor implements MethodInterceptor {
    private Logger logger=Logger.getLogger(MethodCacheInterceptor.class);
    @Resource
    private RedisUtil redisUtil;
    /*
     *不加入缓存的service名称 
     */
    private List<String> targetNamesList;
    /*
     * 不加入缓存的method名称
     */
    private List<String> methodNamesList;
    /*
     * 缓存默认的过期时间
     */
    private Long defaultCacheExpireTime;
    private Long xxxRecordManagerTime;
    private Long xxxSetRecordManagerTime;
    /**
     * 初始化读取不需要加入缓存的类和方法名
     */
    public MethodCacheInterceptor(){
    	try {
    		File file=new File("E:/method/cacheConf.properties");
			InputStream is=new FileInputStream(file);
			Properties p=new Properties();
			p.load(is);
			//分割字符串
			String[] targetNames=p.getProperty("targetNames").split(",");
			String[] methodNames=p.getProperty("methodNames").split(",");
			//加载过期时间设置
			defaultCacheExpireTime=Long.valueOf(p.getProperty("defaultCacheExpireTime"));
			xxxRecordManagerTime=Long.valueOf(p.getProperty("com.etop.xxxRecordManager"));
			xxxSetRecordManagerTime=Long.valueOf(p.getProperty("com.etop.xxxSetRecordManager"));
			//创建list
			targetNamesList=new ArrayList<String>(targetNames.length);
			methodNamesList=new ArrayList<String>(methodNames.length);
			Integer maxLen=targetNames.length>methodNames.length?targetNames.length:methodNames.length;
			//将需要缓存的类名和方法名存入list中
			for(int i=0;i<maxLen;i++){
				if(i<targetNames.length){
					targetNamesList.add(targetNames[i]);
				}
				if(i<methodNames.length){
					methodNamesList.add(methodNames[i]);
				}
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
    }
    
    /**
     * MethodInvocation:相当与method的包装
     * MethodInvocation.getMethod():获得方法
     * MethodInvocation.getArguments():获得方法的参数
     */
	public Object invoke(MethodInvocation invocation) throws Throwable {
		// TODO Auto-generated method stub
		// invocation.proceed():让被拦截的方法继续执行
		Object value=null;
		String targetName=invocation.getThis().getClass().getName();
		String methodName=invocation.getMethod().getName();
		//不需要缓存的内容
		if(!isAddCache(targetName,methodName)){
			//执行方法返回结果
			return invocation.proceed();//让被拦截的方法继续执行
		}
		
		Object[] arguments=invocation.getArguments();
		String key=getCacheKey(targetName,methodName,arguments);
		System.out.println(key);
		try{
		//判断是否有缓存
		if(redisUtil.exists(key)){
			return redisUtil.get(key);
		}
		value=invocation.proceed();
		if(value!=null){
			final String tkey=key;
			final Object tvalue=value;
			new Thread(new Runnable(){
				public void run() {
					// TODO Auto-generated method stub
					if(tkey.startsWith("com.etop.rediscache.xxxRecordManager")){
						redisUtil.set(tkey, tvalue,xxxRecordManagerTime);
					}else if(tkey.startsWith("com.etop.rediscache.xxxSetRecordManager")){
						redisUtil.set(tkey, tvalue, xxxSetRecordManagerTime);
					}else {
						redisUtil.set(tkey, tvalue);
					}
				}
				
			}).start();
			
		}
		}catch(Exception e){
			e.printStackTrace();
			if (value==null){
				return invocation.proceed();
			};
		}
		return value;
	}
   
	/**
	 * 是否加入缓存
	 * @return
	 */
	public boolean isAddCache(String targetName,String methodName){
		boolean flag=true;
		if(targetNamesList.contains(targetName)
				||methodNamesList.contains(methodName)){
			flag=true;
		}
		return flag;
	}
	/**
	 * 创建缓存key
	 * @param targetName 
	 * @param methodName 
	 * @param arguments
	 */
	private String getCacheKey(String targetName,
			                   String methodName,
			                   Object[]arguments){
		StringBuffer sb=new StringBuffer();
		sb.append(targetName).append("_").append(methodName);
		if(arguments!=null&&arguments.length!=0){
			for(int i=0;i<arguments.length;i++){
				sb.append("_").append(arguments[i]);
			}
		}
		return sb.toString();
	}

	public RedisUtil getRedisUtil() {
		return redisUtil;
	}

	public void setRedisUtil(RedisUtil redisUtil) {
		this.redisUtil = redisUtil;
	}

}

